package com.ssy.lingxi.member.merchant.serviceimpl.web;

import com.ssy.lingxi.common.constant.member.MemberLevelTypeEnum;
import com.ssy.lingxi.common.constant.member.MemberStatusEnum;
import com.ssy.lingxi.common.constant.member.MemberTypeEnum;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.member.merchant.api.constant.MemberRelationTypeEnum;
import com.ssy.lingxi.member.merchant.config.ServiceConfig;
import com.ssy.lingxi.member.merchant.entity.MemberDO;
import com.ssy.lingxi.member.merchant.entity.MemberRelationDO;
import com.ssy.lingxi.member.merchant.entity.RoleDO;
import com.ssy.lingxi.member.merchant.model.bo.WorkflowTaskListBO;
import com.ssy.lingxi.member.merchant.model.constant.*;
import com.ssy.lingxi.member.merchant.model.vo.basic.response.MemberTypeIdAndNameVO;
import com.ssy.lingxi.member.merchant.model.vo.basic.response.RoleIdAndNameVO;
import com.ssy.lingxi.member.merchant.model.vo.validate.request.MemberModifyPageVO;
import com.ssy.lingxi.member.merchant.model.vo.validate.request.MemberModifyVO;
import com.ssy.lingxi.member.merchant.model.vo.validate.request.ValidateIdVO;
import com.ssy.lingxi.member.merchant.model.vo.validate.request.ValidateIdsVO;
import com.ssy.lingxi.member.merchant.model.vo.validate.response.MemberModifyDetailVO;
import com.ssy.lingxi.member.merchant.model.vo.validate.response.MemberModifyPageQueryVO;
import com.ssy.lingxi.member.merchant.model.vo.validate.response.MemberModifySearchConditionVO;
import com.ssy.lingxi.member.merchant.repository.MemberRelationRepository;
import com.ssy.lingxi.member.merchant.service.base.*;
import com.ssy.lingxi.member.merchant.service.feign.IWorkflowFeignService;
import com.ssy.lingxi.member.merchant.service.web.IMemberAbilityModifyService;
import com.ssy.lingxi.member.merchant.utils.AgentAreaUtil;
import com.ssy.lingxi.member.merchant.utils.NumberUtil;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 会员资料变更审核相关接口实现类
 * @author 万宁
 * @version 2.0.0
 * @date 2021-05-25
 */
@Service
public class MemberAbilityModifyServiceImpl implements IMemberAbilityModifyService {
    @Resource
    private IBaseMemberCacheService memberCacheService;

    @Resource
    private MemberRelationRepository relationRepository;

    @Resource
    private IBaseMemberDepositDetailService baseMemberDepositDetailService;

    @Resource
    private IBaseMemberQualificationService baseMemberQualificationService;

    @Resource
    private IWorkflowFeignService workflowFeignService;

    @Resource
    private IBaseMemberHistoryService baseMemberHistoryService;

    @Resource
    private IBaseMemberValidateService baseMemberValidateService;

    /**
     * 获取会员变更各个步骤分页查询列表页面下拉框
     *
     * @param headers Http头部信息
     * @return 查询结果
     */
    @Override
    public Wrapper<MemberModifySearchConditionVO> getModifyPageConditions(HttpHeaders headers) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);

        //规则：
        // 1). 上级会员角色为企业会员，下级会员角色为企业会员：无限制
        // 2). 上级会员角色为企业会员，下级会员角色为渠道会员：不允许创建
        // 3). 上级会员角色为渠道会员，下级会员角色为企业会员：不允许创建
        // 4). 上级会员角色为渠道会员，下级会员角色为渠道会员：判断下级会员是否有另一个服务消费者角色在关系树中

        MemberModifySearchConditionVO conditionVO = new MemberModifySearchConditionVO();
        //会员类型（这里返回的是Id）
        List<MemberTypeIdAndNameVO> memberTypeList = baseMemberValidateService.getSubMemberTypeList(loginUser.getMemberType());
        memberTypeList.add(0, new MemberTypeIdAndNameVO(0L, "所有"));
        conditionVO.setMemberTypes(memberTypeList);

        //会员角色（按照Id升序排序）
        List<RoleIdAndNameVO> roleList = baseMemberValidateService.getSubRoleList(loginUser.getMemberType());
        roleList.add(0, new RoleIdAndNameVO(0L, MemberStringEnum.ALL.getName()));
        conditionVO.setRoles(roleList);
        return Wrapper.success(conditionVO);
    }

    /**
     * 分页查询“待审核变更（一级）”会员列表
     *
     * @param headers Http头部新
     * @param pageVO  接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<MemberModifyPageQueryVO>> pageToModifyGradeOne(HttpHeaders headers, MemberModifyPageVO pageVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        return pageModifyRelations(MemberInnerStatusEnum.TO_MODIFY_GRADE_ONE, loginUser.getMemberId(), loginUser.getMemberRoleId(), pageVO.getName(), pageVO.getMemberTypeId(), pageVO.getRoleId(), pageVO.getCurrent(), pageVO.getPageSize());
    }

    /**
     * “待审核变更（一级）” - 查询会员详情
     *
     * @param headers Http头部信息
     * @param idVO    接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<MemberModifyDetailVO> getToModifyGradeOne(HttpHeaders headers, ValidateIdVO idVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        return getMemberModifyDetails(loginUser, idVO.getValidateId());
    }

    /**
     * “待审核变更（一级）” - 审核会员
     *
     * @param headers   Http头部信息
     * @param modifyVO 接口参数
     * @return 审核结果
     */
    @Override
    public Wrapper<Void> toModifyGradeOne(HttpHeaders headers, MemberModifyVO modifyVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        return baseMemberValidateService.execMemberProcess(loginUser, modifyVO.getValidateId(), modifyVO.getAgree(), modifyVO.getReason(), MemberInnerStatusEnum.TO_MODIFY_GRADE_ONE);
    }

    /**
     * “待审核变更（一级）” - 批量审核
     *
     * @param headers Http头部信息
     * @param idVO    接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<Void> batchToModifyGradeOne(HttpHeaders headers, ValidateIdsVO idVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        return baseMemberValidateService.batchExecMemberProcess(loginUser, idVO.getValidateIds(), MemberInnerStatusEnum.TO_MODIFY_GRADE_ONE);
    }

    /**
     * 分页查询“待审核变更（二级）”会员列表
     *
     * @param headers Http头部新
     * @param pageVO  接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<MemberModifyPageQueryVO>> pageToModifyGradeTwo(HttpHeaders headers, MemberModifyPageVO pageVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        return pageModifyRelations(MemberInnerStatusEnum.TO_MODIFY_GRADE_TWO, loginUser.getMemberId(), loginUser.getMemberRoleId(), pageVO.getName(), pageVO.getMemberTypeId(), pageVO.getRoleId(), pageVO.getCurrent(), pageVO.getPageSize());
    }

    /**
     * “待审核变更（二级）” - 查询会员详情
     *
     * @param headers Http头部信息
     * @param idVO    接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<MemberModifyDetailVO> getToModifyGradeTwo(HttpHeaders headers, ValidateIdVO idVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        return getMemberModifyDetails(loginUser, idVO.getValidateId());
    }

    /**
     * “待审核变更（二级）” - 审核会员
     *
     * @param headers   Http头部信息
     * @param modifyVO 接口参数
     * @return 审核结果
     */
    @Override
    public Wrapper<Void> toModifyGradeTwo(HttpHeaders headers, MemberModifyVO modifyVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        return baseMemberValidateService.execMemberProcess(loginUser, modifyVO.getValidateId(), modifyVO.getAgree(), modifyVO.getReason(), MemberInnerStatusEnum.TO_MODIFY_GRADE_TWO);
    }

    /**
     * “待审核变更（二级）” - 批量审核
     *
     * @param headers Http头部信息
     * @param idVO    接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<Void> batchToModifyGradeTwo(HttpHeaders headers, ValidateIdsVO idVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        return baseMemberValidateService.batchExecMemberProcess(loginUser, idVO.getValidateIds(), MemberInnerStatusEnum.TO_MODIFY_GRADE_TWO);
    }

    /**
     * 分页查询“待确认会员变更”会员列表
     *
     * @param headers Http头部新
     * @param pageVO  接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<MemberModifyPageQueryVO>> pageToConfirmModify(HttpHeaders headers, MemberModifyPageVO pageVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        List<MemberInnerStatusEnum> innerStatusEnums = Stream.of(
                MemberInnerStatusEnum.MODIFY_GRADE_ONE_NOT_PASSED,
                MemberInnerStatusEnum.MODIFY_GRADE_TWO_NOT_PASSED,
                MemberInnerStatusEnum.TO_CONFIRM_MODIFY
        ).collect(Collectors.toList());
        return pageModifyRelations(innerStatusEnums, loginUser.getMemberId(), loginUser.getMemberRoleId(), pageVO.getName(), pageVO.getMemberTypeId(), pageVO.getRoleId(), pageVO.getCurrent(), pageVO.getPageSize());
    }

    /**
     * “待确认会员变更” - 查询会员详情
     *
     * @param headers Http头部信息
     * @param idVO    接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<MemberModifyDetailVO> getToConfirmModify(HttpHeaders headers, ValidateIdVO idVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        return getMemberModifyDetails(loginUser, idVO.getValidateId());
    }

    /**
     * “待确认会员变更” - 审核会员
     *
     * @param headers   Http头部信息
     * @param modifyVO 接口参数
     * @return 审核结果
     */
    @Override
    public Wrapper<Void> toConfirmModify(HttpHeaders headers, MemberModifyVO modifyVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        List<MemberInnerStatusEnum> innerStatusEnums = Stream.of(
                MemberInnerStatusEnum.MODIFY_GRADE_ONE_NOT_PASSED,
                MemberInnerStatusEnum.MODIFY_GRADE_TWO_NOT_PASSED,
                MemberInnerStatusEnum.TO_CONFIRM_MODIFY
        ).collect(Collectors.toList());
        return baseMemberValidateService.execMemberProcess(loginUser, modifyVO.getValidateId(), modifyVO.getAgree(), modifyVO.getReason(), innerStatusEnums);
    }

    /**
     * “待确认会员变更” - 批量审核
     *
     * @param headers Http头部信息
     * @param idVO    接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<Void> batchToConfirmModify(HttpHeaders headers, ValidateIdsVO idVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        List<MemberInnerStatusEnum> innerStatusEnums = Stream.of(
                MemberInnerStatusEnum.MODIFY_GRADE_ONE_NOT_PASSED,
                MemberInnerStatusEnum.MODIFY_GRADE_TWO_NOT_PASSED,
                MemberInnerStatusEnum.TO_CONFIRM_MODIFY
        ).collect(Collectors.toList());
        return baseMemberValidateService.batchExecMemberProcess(loginUser, idVO.getValidateIds(), innerStatusEnums);
    }

    /**
     * （重载）分页查询资料变更会员列表
     * @param innerStatusEnum 内部状态
     * @param memberId 当前会员Id
     * @param roleId   当前会员角色Id
     * @param subMemberName  下级会员名称
     * @param subMemberTypeId 下级会员会员类型
     * @param subRoleId  下级会员角色Id
     * @param current    分页参数 - 当前页
     * @param pageSize   分页参数 - 每页行数
     * @return 查询结果
     */
    private Wrapper<PageData<MemberModifyPageQueryVO>> pageModifyRelations(MemberInnerStatusEnum innerStatusEnum, Long memberId, Long roleId, String subMemberName, Long subMemberTypeId, Long subRoleId, int current, int pageSize) {
        return pageModifyRelations(Stream.of(innerStatusEnum).collect(Collectors.toList()), memberId, roleId, subMemberName, subMemberTypeId, subRoleId, current, pageSize);
    }

    /**
     * 分页查询变更会员列表
     * @param innerStatusEnums 内部状态List
     * @param memberId 当前会员Id
     * @param roleId   当前会员角色Id
     * @param subMemberName  下级会员名称
     * @param subMemberTypeId 下级会员会员类型
     * @param subRoleId  下级会员角色Id
     * @param current    分页参数 - 当前页
     * @param pageSize   分页参数 - 每页行数
     * @return 查询结果
     */
    private Wrapper<PageData<MemberModifyPageQueryVO>> pageModifyRelations(List<MemberInnerStatusEnum> innerStatusEnums, Long memberId, Long roleId, String subMemberName, Long subMemberTypeId, Long subRoleId, int current, int pageSize) {
        Pageable pageable = PageRequest.of(current - 1, pageSize, Sort.by("id").descending());
        Specification<MemberRelationDO> specification = (Specification<MemberRelationDO>) (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("memberId").as(Long.class), memberId));
            list.add(criteriaBuilder.equal(root.get("roleId").as(Long.class), roleId));
            list.add(criteriaBuilder.equal(root.get("relType").as(Integer.class), MemberRelationTypeEnum.OTHER.getCode()));
            if(innerStatusEnums.size() == 1) {
                list.add(criteriaBuilder.equal(root.get("innerStatus").as(Integer.class), innerStatusEnums.get(0).getCode()));
            } else {
                Expression<Integer> exp = root.get("innerStatus");
                list.add(exp.in(innerStatusEnums.stream().map(MemberInnerStatusEnum::getCode).collect(Collectors.toList())));
            }

            //下级会员名称
            if(StringUtils.hasLength(subMemberName)) {
                Join<MemberRelationDO, MemberDO> subMemberJoin = root.join("subMember", JoinType.LEFT);
                list.add(criteriaBuilder.like(subMemberJoin.get("name").as(String.class), "%" + subMemberName.trim() + "%"));
            }

            //下级会员类型
            if(NumberUtil.notNullOrZero(subMemberTypeId)) {
                Join<MemberRelationDO, RoleDO> subRoleJoin = root.join("subRole", JoinType.LEFT);
                list.add(criteriaBuilder.equal(subRoleJoin.get("memberType").get("id").as(Long.class), subMemberTypeId));
            }

            //下级会员角色
            if(NumberUtil.notNullOrZero(subRoleId)) {
                list.add(criteriaBuilder.equal(root.get("subRoleId").as(Long.class), subRoleId));
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        Page<MemberRelationDO> pageList = relationRepository.findAll(specification, pageable);
        return Wrapper.success(new PageData<>(pageList.getTotalElements(), pageList.getContent().stream().map(relationDO -> {
            MemberModifyPageQueryVO queryVO = new MemberModifyPageQueryVO();
            queryVO.setValidateId(relationDO.getId());
            queryVO.setMemberId(relationDO.getSubMemberId());
            queryVO.setName(relationDO.getSubMember().getName());
            queryVO.setMemberTypeName(MemberTypeEnum.getCodeMessage(relationDO.getSubRole().getMemberType().getTypeEnum()));
            queryVO.setRoleName(relationDO.getSubRole().getRoleName());
            queryVO.setInnerStatus(relationDO.getInnerStatus());
            queryVO.setInnerStatusName(MemberInnerStatusEnum.getCodeMsg(relationDO.getInnerStatus()));
            queryVO.setOuterStatus(relationDO.getOuterStatus());
            queryVO.setOuterStatusName(MemberOuterStatusEnum.getCodeMsg(relationDO.getOuterStatus()));
            return queryVO;
        }).collect(Collectors.toList())));
    }


    /**
     * 查询会员变更详细信息
     * @param loginUser  登录用户
     * @param validateId 会员关系Id
     * @return 查询结果
     */
    private Wrapper<MemberModifyDetailVO> getMemberModifyDetails(UserLoginCacheDTO loginUser, Long validateId) {
        MemberRelationDO relationDO = relationRepository.findById(validateId).orElse(null);
        if(relationDO == null || !relationDO.getMemberId().equals(loginUser.getMemberId()) || !relationDO.getRoleId().equals(loginUser.getMemberRoleId())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_RELATION_DOES_NOT_EXIST);
        }

        Wrapper<WorkflowTaskListBO> result = workflowFeignService.listMemberProcessSteps(loginUser.getMemberId(), relationDO.getValidateTask().getProcessKey(), relationDO.getValidateTask().getTaskId());
        if(result.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(result.getCode(), result.getMessage());
        }

        MemberModifyDetailVO detailVO = new MemberModifyDetailVO();
        detailVO.setOuterVerifySteps(baseMemberValidateService.getMemberModifyOuterSteps(relationDO));
        detailVO.setCurrentOuterStep(2);

        detailVO.setInnerVerifySteps(result.getData().getStepList());
        detailVO.setCurrentInnerStep(result.getData().getCurrentStep());

        detailVO.setValidateId(relationDO.getId());
        detailVO.setMemberId(relationDO.getSubMemberId());
        detailVO.setName(relationDO.getSubMember().getName());
        detailVO.setOuterStatus(relationDO.getOuterStatus());
        detailVO.setOuterStatusName(MemberOuterStatusEnum.getCodeMsg(relationDO.getOuterStatus()));
        detailVO.setInnerStatus(relationDO.getInnerStatus());
        detailVO.setInnerStatusName(MemberInnerStatusEnum.getCodeMsg(relationDO.getInnerStatus()));
        detailVO.setStatus(relationDO.getStatus());
        detailVO.setStatusName(MemberStatusEnum.getCodeMessage(relationDO.getStatus()));
        detailVO.setMemberTypeEnum(relationDO.getSubMemberTypeEnum());
        detailVO.setMemberTypeName(MemberTypeEnum.getCodeMessage(relationDO.getSubMemberTypeEnum()));
        detailVO.setRoleName(relationDO.getSubRoleName());
        detailVO.setLevel(relationDO.getLevelRight() == null ? 0 : relationDO.getLevelRight().getLevel());
        detailVO.setLevelTag(relationDO.getLevelRight() == null ? "" : relationDO.getLevelRight().getLevelTag());
        detailVO.setAccount(relationDO.getSubMember().getAccount());
        detailVO.setPhone(relationDO.getSubMember().getPhone());
        detailVO.setEmail(relationDO.getSubMember().getEmail());
        detailVO.setRegisterTime(relationDO.getCreateTime().format(ServiceConfig.DEFAULT_DATETIME_FORMATTER));
        //渠道信息
        if(relationDO.getSubMemberLevelTypeEnum().equals(MemberLevelTypeEnum.CHANNEL.getCode())) {
            if(relationDO.getChannel() == null) {
                return Wrapper.fail(ResponseCode.MC_MS_SUB_MEMBER_CHANNEL_DOES_NOT_EXIST);
            }

            detailVO.setChannelLevelTag(relationDO.getChannel().getChannelLevelTag());
            detailVO.setChannelTypeName(MemberChannelTypeEnum.getMsg(relationDO.getChannel().getChannelType().getChannelTypeEnum()));
            detailVO.setAreas(AgentAreaUtil.transferToList(relationDO.getChannel().getAgentArea()));
            detailVO.setRemark(StringUtils.hasLength(relationDO.getChannel().getRemark()) ? relationDO.getChannel().getRemark() : "");
        } else {
            detailVO.setChannelLevelTag("");
            detailVO.setChannelTypeName("");
            detailVO.setAreas(new ArrayList<>());
            detailVO.setRemark("");
        }

        //入库资料
        detailVO.setDepositDetails(baseMemberDepositDetailService.mergeMemberDepositoryDetailText(relationDO));

        //资质证明
        detailVO.setQualities(baseMemberQualificationService.findMemberQualities(relationDO));

        //内、外部历史记录
        detailVO.setInnerHistory(baseMemberHistoryService.listMemberInnerHistory(relationDO));
        detailVO.setOuterHistory(baseMemberHistoryService.listMemberOuterHistory(relationDO));

        return Wrapper.success(detailVO);
    }
}
